package com.cskaoyan.wordmemorize.aop;

import com.cskaoyan.wordmemorize.auth.SaAdminCheckPermission;
import com.cskaoyan.wordmemorize.auth.StpKit;
import com.cskaoyan.wordmemorize.common.result.Result;
import com.cskaoyan.wordmemorize.dao.entity.OperateLogDO;
import com.cskaoyan.wordmemorize.service.AdminLogService;
import groovy.lang.Lazy;
import io.swagger.v3.core.util.Json;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.sql.Timestamp;

// 定义切面类
@Aspect
@Component
public class AdminOperateLogAspect {
    /*
        AdminLogService 可能间接依赖了被 @MyOperateLog 注解标记的类/方法
        表现：启动时抛出 BeanCurrentlyInCreationException
        解决方案延缓加载 @Lazy注解
     */
    @Lazy  // 添加延迟加载
    @Autowired
    AdminLogService adminLogService;
    // 定义切入点PointCut@MyOperateLog
//    @Pointcut("@annotation(com.cskaoyan.wordmemorize.aop.MyOperateLog) && " +
//            "!within(com.cskaoyan.wordmemorize.service.AdminLogService)")
//    public void adminOperateLogRecord(){
//    }
//
//    @Around("adminOperateLogRecord()")
//    public Object adminOperateLog(ProceedingJoinPoint joinPoint){
//
//        try {
//            Object target = joinPoint.getTarget();
//            // 获取方法签名
//            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
//            // 获取方法
//            Method method = signature.getMethod();
//            // 获取方法上的注解
//            MyOperateLog operateLog = method.getAnnotation(MyOperateLog.class);
//            // 1. 获取操作类型
//            int operateType = operateLog.operateType();
//            // 2. 获取操作数据的描述
//            String dateType = operateLog.dateType();
//            // 获取方法的返回值
//            Object[] args = joinPoint.getArgs();
//            Object result = null;
//            Integer status = 0;
//            try {
//                result = joinPoint.proceed(args);
//                status = 1;
//            } catch (Throwable e) {
//                throw new RuntimeException(e);
//            }finally {
//                // 获取data
//                String data = "";
//                switch (operateType){
//                    case 1:
//                    case 2:
//                        // 修改数据，将阐述封装为对象再转换为Json字符存入日志
//                    case 5:
//                        // 新增和修改数据,请求参数存入日志
//                        // 将参数转换为Json字符串
//                        String argsString = Json.mapper().writeValueAsString(args);
//                        data = argsString;
//                        break;
//                    case 3:
//                    case 4:
//                        // 删除数据，将返回值存入日志
//                    case 6:
//                        // excel导入数据 将返回值值存入日志
//                        // 将返回值转换为Json字符串
//                        String resultString = Json.mapper().writeValueAsString(result);
//                        data = resultString;
//                        break;
//                }
//
//                OperateLogDO operateLogDO = new OperateLogDO();
//                operateLogDO.setEmployeeId(StpKit.ADMIN.getLoginIdAsLong());
//                operateLogDO.setDataType(dateType);
//                operateLogDO.setOperateType(operateType);
//                operateLogDO.setData(data);
//                operateLogDO.setStatus(status);
//                operateLogDO.setCreateTime(new Timestamp(System.currentTimeMillis()));
//                boolean b = adminLogService.save(operateLogDO);
//                System.out.println(b);
//            }
//
//            return result;
//
//        } catch (Throwable e) {
//            throw new RuntimeException(e);
//        }
//
//    }

    // 定义切入点PointCut为被@SaAdminCheckPermission注解标记的方法
    @Pointcut("@annotation(com.cskaoyan.wordmemorize.auth.SaAdminCheckPermission) && " +
            "!within(com.cskaoyan.wordmemorize.service.AdminLogService)")
    public void adminOperateLogRecordWithSaAdminCheckPermission(){
    }

    @Around("adminOperateLogRecordWithSaAdminCheckPermission()")
    public Object adminOperateLogWithSaAdminCheckPermission(ProceedingJoinPoint joinPoint){
        try{
            // 获取方法 获取方法上的注解
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            Method method = signature.getMethod();
            SaAdminCheckPermission saAdminCheckPermission = method.getAnnotation(SaAdminCheckPermission.class);
            // 获取权限
            String[] value = saAdminCheckPermission.value();
            String perMission = value[0];
            // 获取操作类型
            int operateType = 0;
            {
                if(perMission.endsWith("add")){
                    operateType = 1;
                }else if (perMission.endsWith("update")){
                    operateType = 4;
                }else if (perMission.endsWith("delete")){
                    if (perMission.endsWith("batchdelete")){
                        operateType = 3;
                    }else {
                        operateType = 2;
                    }
                }else if (perMission.endsWith("authorize")||perMission.endsWith("add:sub")){
                    operateType = 5;
                }else if (perMission.endsWith("excel:upload")){
                    operateType = 6;
                }

            }
            // 获取方法的返回值
            Object[] args = joinPoint.getArgs();
            Object result = null;
            Integer status = 0;
            try {
                result = joinPoint.proceed(args);
                status = 1;
            } catch (Throwable e) {
                throw new RuntimeException(e);
            }finally {


                if(operateType != 0){
                    String dateType = "";
                    {
                        if(perMission.contains("admin:book") || perMission.contains("10001")){
                            dateType = "书籍";
                        }else if(perMission.contains("admin:category") || perMission.contains("10002")) {
                            dateType = "书籍类目";
                        }else if(perMission.contains("admin:chapter") || perMission.contains("10003")) {
                            dateType = "章节";
                        }else if(perMission.contains("admin:voc") || perMission.contains("10004")) {
                            dateType = "词汇";
                        }else if(perMission.contains("excel") || perMission.contains("10004005")) {
                            dateType = "excel";
                        }else if(perMission.contains("admin:topic") || perMission.contains("10005")) {
                            dateType = "题目";
                        }else if(perMission.contains("admin:employee") || perMission.contains("20001")) {
                            dateType = "员工管理";
                        }else if(perMission.contains("admin:role") || perMission.contains("20002")) {
                            dateType = "角色管理";
                        }else if(perMission.contains("admin:permission") || perMission.contains("20003")) {
                            dateType = "权限管理";
                        }else if(perMission.contains("admin:goods") || perMission.contains("30001")) {
                            dateType = "商品";
                        }else if(perMission.contains("admin:level") || perMission.contains("40001")) {
                            dateType = "等级管理";
                        }else if(perMission.contains("admin:privilege") || perMission.contains("40002")) {
                            dateType = "等级特权管理";
                        }
                    }
                    // 获取data
                    String data = "";
                    switch (operateType){
                        case 1:
                        case 2:
                            // 修改数据，将阐述封装为对象再转换为Json字符存入日志
                        case 5:
                            // 新增和修改数据,请求参数存入日志
                            // 将参数转换为Json字符串
                            String argsString = Json.mapper().writeValueAsString(args);
                            data = argsString;
                            break;
                        case 3:
                        case 4:
                            // 删除数据，将返回值存入日志
                        case 6:
                            // excel导入数据 将返回值值存入日志
                            // 将返回值转换为Json字符串
                            String resultString = Json.mapper().writeValueAsString(result);
                            data = resultString;
                            break;
                    }

                    OperateLogDO operateLogDO = new OperateLogDO();
                    operateLogDO.setEmployeeId(StpKit.ADMIN.getLoginIdAsLong());
                    operateLogDO.setDataType(dateType);
                    operateLogDO.setOperateType(operateType);
                    operateLogDO.setData(data);
                    operateLogDO.setStatus(status);
                    operateLogDO.setCreateTime(new Timestamp(System.currentTimeMillis()));
                    boolean b = adminLogService.save(operateLogDO);
                    System.out.println(b);
                }

            }

            if(operateType == 3 ||operateType == 4){
                return Result.ok();
            }
            return result;

        } catch (Throwable e) {
            throw new RuntimeException(e);
        }
    }
}
